<?php


namespace EchoPHP\Foundation\Support;


class HeaderBag implements \IteratorAggregate, \Countable {

    protected $headers = [];
    protected $cacheControl = [];

    public function __construct(array $headers = []) {
        foreach ($headers as $key => $value) {
            $this->set($key, $value);
        }
    }

    /**
     * 输出头信息的字符串格式
     * @return string
     */
    public function __toString() {
        if (empty($headers = $this->headers)) {
            return '';
        }

        ksort($headers);
        $max = max(array_map('strlen', array_keys($headers))) + 1;
        $content = '';
        foreach ($headers as $name => $values) {
            $name = ucwords($name, '-');
            foreach ($values as $value) {
                $content .= sprintf("%-{$max}s %s\r\n", $name . ':', $value);
            }
        }
        return $content;
    }

    public function all() {
        return $this->headers;
    }

    public function keys() {
        return array_keys($this->headers);
    }

    public function replace(array $headers = []) {
        foreach ($headers as $key => $value) {
            $this->set($key, $value);
        }
    }

    public function add(array $headers = []) {
        foreach ($headers as $key => $value) {
            $this->set($key, $value);
        }
    }

    /**
     * 获取header信息
     * @param $key
     * @param null $default
     * @param bool $first 是否只获取第一个头信息
     * @return array|mixed|null
     */
    public function get($key, $default = null, $first = true) {
        $key = $this->getHeaderKey($key);
        if (!isset($this->headers[$key])) {
            if (is_null($default)) {
                return $first ? null : [];
            }
            return $first ? $default : [$default];
        }
        return $first ? $this->headers[$key][0] : $this->headers[$key];
    }

    /**
     * 设置header信息
     * @param $key
     * @param $values
     * @param bool $replace
     */
    public function set($key, $values, $replace = true) {
        $key = $this->getHeaderKey($key);
        if (is_array($values)) {
            $values = array_values($values);

            if ($replace || !isset($this->headers[$key])) {
                $this->headers[$key] = $values;
            } else {
                $this->headers[$key] = array_merge($this->headers[$key], $values);
            }
        } else {
            if ($replace || !isset($this->headers[$key])) {
                $this->headers[$key] = [$values];
            } else {
                $this->headers[] = $values;
            }
        }

        if ('cache-control' === $key) {
            $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key]));
        }
    }

    public function has($key) {
        return array_key_exists($this->getHeaderKey($key), $this->headers);
    }

    public function remove($key) {
        $key = $this->getHeaderKey($key);
        unset($this->headers[$key]);
    }

    /**
     * 获取cache-control相关header头信息
     * @return string
     */
    public function getCacheControlHeader() {
        ksort($this->cacheControl);

        return HeaderUtils::toString($this->cacheControl, ',');
    }

    /**
     * 解析头信息缓存标记
     * @param $header
     * @return array
     */
    public function parseCacheControl($header) {
        $parts = HeaderUtils::split($header, ',=');

        return HeaderUtils::combine($parts);
    }

    /**
     * 判断文档是否有缓存标记
     * @param $key
     * @return bool
     */
    public function hasCacheControlDirective($key) {
        return array_key_exists($key, $this->cacheControl);
    }

    /**
     * 获取一项cache-control
     * @param $key
     * @return mixed|null
     */
    public function getCacheControlDirective($key) {
        return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
    }

    /**
     * 添加一项cache-control
     * @param $key
     * @param bool $value
     */
    public function addCacheControlDirective($key, $value = true) {
        $this->cacheControl[$key] = $value;
        $this->set('Cache-Control', $this->getCacheControlHeader());
    }

    /**
     * 移除一项cache-control
     * @param $key
     */
    public function removeCacheControllerDirective($key) {
        if (isset($this->cacheControl[$key])) {
            unset($this->cacheControl[$key]);

            $this->set('Cache-Control', $this->getCacheControlHeader());
        }
    }


    /**
     * 获取头信息的标准名称，小写 '-' 分隔
     * @param $key
     * @return mixed
     */
    protected function getHeaderKey($key) {
        return str_replace('_', '-', strtolower($key));
    }

    public function getIterator() {
        return new \ArrayIterator($this->headers);
    }

    public function count() {
        return count($this->headers);
    }
}